﻿using BattleBotsMattAndSunny.Components.Interfaces;
using BattleBotsMattAndSunny.Model;
using Robocode;
using Robocode.Util;
using System;

namespace BattleBotsMattAndSunny.Components.Treads
{
    public class LockTreads : ITreadsManager
    {
        public IDataManager dataManager { get; set; }

        public AdvancedRobot robot { get; set; }

        public Enemy CurrentTarget { get; set; }

        private int turnDirection = 1; // Clockwise or counterclockwise

        public LockTreads(IDataManager dm, AdvancedRobot r)
        {
            dataManager = dm;
            robot = r;
        }

        public void OnScannedRobot(ScannedRobotEvent e)
        {
            CurrentTarget = dataManager.GetEnemy(e.Name);

            if (e.Name == CurrentTarget.Name)
            {
                if (e.Bearing >= 0)
                {
                    turnDirection = 1;
                }
                else
                {
                    turnDirection = -1;
                }

                robot.TurnRight(e.Bearing);
                robot.SetAhead(e.Distance / 3);
                robot.Scan(); // Might want to move ahead again!
            }
        }

        public void OnHitWall(HitWallEvent e)
        {
            robot.Back(robot.BattleFieldHeight / 4);
        }

        public void OnHitByBullet(HitByBulletEvent e)
        {
            //Determine location and correct?
            //Rely on scanner....
        }

        public void Move()
        {
            if (IsNearWalls())
            {
                robot.SetAhead(0);
                robot.TurnRight(AngleToCenter());
                robot.SetAhead(20);
            }
            else
                robot.TurnRight(6 * turnDirection);
        }

        private bool IsNearWalls()
        {
            double MarginY = (robot.Height + robot.Width) * 4;
            double MarginX = MarginY;
            return (robot.Y > robot.BattleFieldHeight - MarginY || robot.Y < MarginY) ||
                   (robot.X > robot.BattleFieldWidth - MarginX || robot.X < MarginX);
        }

        private double AngleToPoint(double x, double y)
        {
            // can rotate the coordinate system to avoid the addition of pi/2 if you like
            double b = Math.PI / 2 - Math.Atan2(y - robot.Y, x - robot.Y);
            return Utils.NormalRelativeAngle(b - robot.HeadingRadians);
        }

        private double AngleToCenter()
        {
            return AngleToPoint(robot.BattleFieldWidth / 2, robot.BattleFieldHeight / 2);
        }
    }
}